import torch
from torch import nn
class DoubleConv(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(DoubleConv, self).__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1),
            nn.BatchNorm2d(out_channels),
            nn.ReLU(inplace=True),
            nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1),
            nn.BatchNorm2d(out_channels),
            nn.ReLU(inplace=True)
        )

    def forward(self, x):
        return self.conv(x)

class UNet(nn.Module):
    def __init__(self, picture_size:int):
        """
        :param picture_size: 输入图片的边长
        """
        super(UNet,self).__init__()
        # 图片形状：(batch_size, num_channels, picture_size, picture_size)
        # 小心图片是多通道的
        self.picture_size = picture_size
        
        self.inc = DoubleConv(3, 64)
        self.down1 = nn.MaxPool2d(2)
        self.conv1 = DoubleConv(64, 128)
        self.down2 = nn.MaxPool2d(2)
        self.conv2 = DoubleConv(128, 256)
        self.down3 = nn.MaxPool2d(2)
        self.conv3 = DoubleConv(256, 512)
        self.down4 = nn.MaxPool2d(2)
        self.conv4 = DoubleConv(512, 1024)
        self.up1 = nn.ConvTranspose2d(1024, 512, kernel_size=2, stride=2)
        self.upconv1 = DoubleConv(1024, 512)
        self.up2 = nn.ConvTranspose2d(512, 256, kernel_size=2, stride=2)
        self.upconv2 = DoubleConv(512, 256)
        self.up3 = nn.ConvTranspose2d(256, 128, kernel_size=2, stride=2)
        self.upconv3 = DoubleConv(256, 128)
        self.up4 = nn.ConvTranspose2d(128, 64, kernel_size=2, stride=2)
        self.upconv4 = DoubleConv(128, 64)
        self.outc = nn.Conv2d(64, 3, kernel_size=1)

    
    def forward(self,x):
        # 针对多通道问题，进行通道展开
        #x=x.view(-1, self.picture_size, self.picture_size)
        x1 = self.inc(x)
        x2 = self.down1(x1)
        x2 = self.conv1(x2)
        x3 = self.down2(x2)
        x3 = self.conv2(x3)
        x4 = self.down3(x3)
        x4 = self.conv3(x4)
        x5 = self.down4(x4)
        x5 = self.conv4(x5)
        x = self.up1(x5)
        x = torch.cat([x, x4], dim=1)
        x = self.upconv1(x)
        x = self.up2(x)
        x = torch.cat([x, x3], dim=1)
        x = self.upconv2(x)
        x = self.up3(x)
        x = torch.cat([x, x2], dim=1)
        x = self.upconv3(x)
        x = self.up4(x)
        x = torch.cat([x, x1], dim=1)
        x = self.upconv4(x)
        x = self.outc(x)
        return x